define("arale/dialog/1.1.3/dialog",
	["$","arale/overlay/1.1.2/overlay",
	 "arale/position/1.0.1/position",
	 "arale/iframe-shim/1.0.2/iframe-shim",
	 "arale/widget/1.1.1/widget",
	 "arale/base/1.1.1/base",
	 "arale/class/1.1.0/class",
	 "arale/events/1.1.0/events",
	 "arale/overlay/1.1.2/mask",
	 "arale/templatable/0.9.1/templatable",
	 "gallery/handlebars/1.0.2/handlebars",
	 "./dialog.handlebars",
	 "./dialog.css"],
function(require, exports, module){
		
	var $ = require("$"),
		Overlay=require("arale/overlay/1.1.2/overlay"),
		mask=require("arale/overlay/1.1.2/mask"),
		Events=require("arale/events/1.1.0/events"),
		templatable=require("arale/templatable/0.9.1/templatable"),
		DEFAULT_HEIGHT = "500px",
		
		Dialog=Overlay.extend({
			// 模板
			Implements:templatable,
			attrs:{
				template:require("./dialog.handlebars"),
				trigger:{
					value:null,
					getter:function(a){
						return $(a);
					}
				},
				classPrefix:"ui-dialog",
				
				// 指定内容元素，可以是 url 地址
				content: {
	                value: null,
	                setter: function(val) {
	                    // 判断是否是 url 地址
	                    if (/^(https?:\/\/|\/|\.\/|\.\.\/)/.test(val)) {
	                        this._type = 'iframe';
	                    }
	                    return val;
	                }
	            },
				
	            // 是否有背景遮罩层
	            // 可设为 false
	            hasMask: {
	                hideOnClick: true
	            },
				
	            // 关闭按钮可以自定义
	            closeTpl: '×',

	            // 默认宽度
	            width: 500,

	            // 默认高度
	            height: null,

	            // 简单的动画效果 none | fade
	            effect: 'none',

	            // 不用解释了吧
	            zIndex: 999,

	            // 是否自适应高度
	            autoFit: true,

	            // 默认定位居中
	            align: {
	                selfXY: ['50%', '50%'],
	                baseXY: ['50%', '50%']
	            }
			},
			
			parseElement: function() {
	            this.set("model", {
	                classPrefix: this.get('classPrefix')
	            });

	            Dialog.superclass.parseElement.call(this);

	            this.contentElement = this.$('[data-role=content]');
	            // 必要的样式
	            this.contentElement.css({
	                background: '#fff',
	                height: '100%',
	                zoom: 1
	            });
	            // 关闭按钮先隐藏
	            // 后面当 onRenderCloseTpl 时，如果 closeTpl 不为空，会显示出来
	            // 这样写是为了回避 arale.base 的一个问题：
	            // 当属性初始值为''时，不会进入 onRender 方法
	            // https://github.com/aralejs/base/issues/7
	            this.$('[data-role=close]').hide();
	        },
		
	        events: {
	            'click [data-role=close]': function(e) {
	                e.preventDefault();
	                this.hide();
	            }
	        },
		
	        show: function() {
	            // iframe 要在载入完成才显示
	            if (this._type === 'iframe') {
	                // iframe 还未请求完，先设置一个固定高度
	                !this.get('height') && this.element.css('height', DEFAULT_HEIGHT);
	                this._showIframe();
	            }
	            
	            Dialog.superclass.show.call(this);
	            return this;
	        },
		
	        hide: function() {
	            // 把 iframe 状态复原
	            if (this._type === 'iframe' && this.iframe) {
	                this.iframe.attr({
	                    src: 'javascript:\'\';'
	                });
	                // 原来只是将 iframe 的状态复原
	                // 但是发现在 IE6 下，将 src 置为 javascript:''; 会出现 404 页面
	                this.iframe.remove();
	                this.iframe = null;
	            }

	            Dialog.superclass.hide.call(this);
	            clearInterval(this._interval);
	            delete this._interval;
	            return this;
	        },
		
	        destroy: function() {
	            this.element.remove();
	            this.get('hasMask') && mask.hide();
	            clearInterval(this._interval);
	            return Dialog.superclass.destroy.call(this);
	        },
		
	        setup: function() {
	            Dialog.superclass.setup.call(this);

	            this._setupTrigger();
	            this._setupMask();
	            this._setupKeyEvents();
	            this._setupFocus();
	            toTabed(this.element);
	            toTabed(this.get('trigger'));

	            // 默认当前触发器
	            this.activeTrigger = this.get('trigger').eq(0);
	        },
		
	        _onRenderContent: function(val) {
	            if (this._type !== 'iframe') {
	                var value;
	                // 有些情况会报错
	                try {
	                    value = $(val);
	                } catch (e) {
	                    value = [];
	                }
	                if (value[0]) {
	                    this.contentElement.empty().append(value);
	                } else {
	                    this.contentElement.empty().html(val);
	                }
	            }
	        },
	        
	        _onRenderCloseTpl: function(val) {
	            if (val === '') {
	                this.$('[data-role=close]').html(val).hide();
	            } else {
	                this.$('[data-role=close]').html(val).show();
	            }
	        },
		
	        // 覆盖 overlay，提供动画
	        _onRenderVisible: function(val) {
	            if (val) {
	                if (this.get('effect') === 'fade') {
	                    // 固定 300 的动画时长，暂不可定制
	                    this.element.fadeIn(300);
	                } else {
	                    this.element.show();
	                }
	            } else {
	                this.element.hide();
	            }
	        },
		
	        // 私有方法
	        // ---

	        // 绑定触发对话框出现的事件
	        _setupTrigger: function() {
	            this.delegateEvents(this.get('trigger'), 'click', function(e) {
	                e.preventDefault();
	                // 标识当前点击的元素
	                this.activeTrigger = $(e.currentTarget);
	                this.show();
	            });
	        },

		
	     // 绑定遮罩层事件
	        _setupMask: function() {
	            var hasMask = this.get('hasMask');
	            var zIndex = parseInt(this.get('zIndex'), 10);
	            var oldZIndex = null;
	            var that = this;

	            this.before('show', function() {
	                if (hasMask) {
	                    oldZIndex =  mask.get('zIndex');
	                    mask.set('zIndex', zIndex - 1).show();
	                    
	                    // 点击遮罩关闭对话框
	                    if (hasMask.hideOnClick) {
	                        mask.element.one('click', function() {
	                            that.hide();
	                        });
	                    }
	                }
	            });
	            this.after('hide', function() {
	                if (hasMask) {
	                    mask.set('zIndex', oldZIndex).hide();
	                }
	            });
	        },
		
	        // 绑定元素聚焦状态
	        _setupFocus: function() {
	            this.after('show', function() {
	                this.element.focus();
	            });
	            this.after('hide', function() {
	                // 关于网页中浮层消失后的焦点处理
	                // http://www.qt06.com/post/280/
	                this.activeTrigger && this.activeTrigger.focus();
	            });
	        },
	        
	     // 绑定键盘事件，ESC关闭窗口
	        _setupKeyEvents: function() {
	            this.delegateEvents($(document), 'keyup', function(e) {
	                if (e.keyCode === 27) {
	                    this.get('visible') && this.hide();
	                }
	            });
	        },

	        _showIframe: function() {
	            var that = this;
	            // 若未创建则新建一个
	            if (!this.iframe) {
	                this._createIframe();
	            }
	            // 开始请求 iframe
	            this.iframe.attr({
	                src: this._fixUrl(),
	                name: 'dialog-iframe' + new Date().getTime()
	            });
	            // 因为在 IE 下 onload 无法触发
	            // http://my.oschina.net/liangrockman/blog/24015
	            // 所以使用 jquery 的 one 函数来代替 onload
	            // one 比 on 好，因为它只执行一次，并在执行后自动销毁
	            this.iframe.one('load', function() {
	                // 如果 dialog 已经隐藏了，就不需要触发 onload
	                if (!that.get('visible')) {
	                    return;
	                }
	                // 绑定自动处理高度的事件
	                if (that.get('autoFit')) {
	                    clearInterval(that._interval);
	                    that._interval = setInterval(function() {
	                        that._syncHeight();
	                    }, 300);
	                }
	                that._syncHeight();
	                that._setPosition();
	                that.trigger('complete:show');
	            });
	        },
	        
	        _fixUrl: function() {
	            var s = this.get('content').match(/([^?#]*)(\?[^#]*)?(#.*)?/);
	            s.shift();
	            s[1] = ((s[1] && s[1] !== '?') ? (s[1] + '&') : '?') +
	                't=' + new Date().getTime();
	            return s.join('');
	        },

	        _createIframe: function() {
	            var that = this;

	            this.iframe = $('<iframe>', {
	                src: 'javascript:\'\';',
	                scrolling: 'no',
	                frameborder: 'no',
	                allowTransparency: 'true',
	                css: {
	                    border: 'none',
	                    width: '100%',
	                    display: 'block',
	                    height: '100%',
	                    overflow: 'hidden'
	                }
	            }).appendTo(this.contentElement);

	            // 给 iframe 绑一个 close 事件
	            // iframe 内部可通过 window.frameElement.trigger('close') 关闭
	            Events.mixTo(this.iframe[0]);
	            this.iframe[0].on('close', function() {
	                that.hide();
	            });
	        },
	        
	        _syncHeight: function() {
	            var h = null;
	            // 如果未传 height，才会自动获取
	            if (!this.get('height')) {
	                try {
	                    this._errCount = 0;
	                    h = getIframeHeight(this.iframe) + 'px';
	                } catch (err) {
	                    // 页面跳转也会抛错，最多失败6次
	                    this._errCount = (this._errCount || 0) + 1;
	                    if (this._errCount >= 6) {
	                        // 获取失败则给默认高度 300px
	                        // 跨域会抛错进入这个流程
	                        h = DEFAULT_HEIGHT;
	                        clearInterval(this._interval);
	                        delete this._interval;
	                    }
	                }
	                
	                this.element.css('height', h);
	                // force to reflow in ie6
	                // http://44ux.com/blog/2011/08/24/ie67-reflow-bug/
	                this.element[0].className = this.element[0].className;
	            } else {
	                clearInterval(this._interval);
	                delete this._interval;
	            }
	        }
		
		});

	module.exports=Dialog,
	module.exports.outerBoxClass="arale-dialog-1_1_3";
	
	// 让目标节点可以被 Tab
    function toTabed(element) {
        if (element.attr('tabindex') == null) {
            element.attr('tabindex', '-1');
        }
    }
	
    // 获取 iframe 内部的高度
    function getIframeHeight(iframe) {
        var D = iframe[0].contentWindow.document;
        if (D.body.scrollHeight && D.documentElement.scrollHeight) {
            return Math.min(
                D.body.scrollHeight,
                D.documentElement.scrollHeight
            );
        } else if (D.documentElement.scrollHeight) {
            return D.documentElement.scrollHeight;
        } else if (D.body.scrollHeight) {
            return D.body.scrollHeight;
        }
    }
	
});

define("arale/dialog/1.1.3/dialog.handlebars", ["gallery/handlebars/1.0.2/runtime"], function(require, exports, module) {
    var Handlebars = require("gallery/handlebars/1.0.2/runtime");
    var template = Handlebars.template;
    module.exports = template(function(Handlebars, depth0, helpers, partials, data) {
        this.compilerInfo = [ 3, ">= 1.0.0-rc.4" ];
        helpers = helpers || {};
        for (var key in Handlebars.helpers) {
            helpers[key] = helpers[key] || Handlebars.helpers[key];
        }
        data = data || {};
        var buffer = "", stack1, functionType = "function", escapeExpression = this.escapeExpression;
        buffer += '<div class="';
        if (stack1 = helpers.classPrefix) {
            stack1 = stack1.call(depth0, {
                hash: {},
                data: data
            });
        } else {
            stack1 = depth0.classPrefix;
            stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1;
        }
        buffer += escapeExpression(stack1) + '"><div class="';
        if (stack1 = helpers.classPrefix) {
            stack1 = stack1.call(depth0, {
                hash: {},
                data: data
            });
        } else {
            stack1 = depth0.classPrefix;
            stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1;
        }
        buffer += escapeExpression(stack1) + '-content" data-role="content"></div>\n</div>\n';
        
        return buffer;
    });
});




